package com.mask.im.business.handler;

import cn.hutool.core.util.BooleanUtil;
import com.mask.im.business.annotation.AesCrypto;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.IOException;
import java.lang.reflect.Type;

/**
 * 请求体解密处理器
 * 负责对带有@AesCrypto注解的请求体进行解密处理
 * 
 * @author jian
 */
@Log4j2
@ControllerAdvice
@Component
public class DecryptRequestBodyAdviceHandler implements RequestBodyAdvice {

    @Value("${crypto.charset:UTF-8}")
    private String charset;
    
    @Value("${crypto.key:}")
    private String key;
    
    @Autowired
    private CryptoService cryptoService;

    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        // 检查方法或类是否有@AesCrypto注解
        return hasAesCryptoAnnotation(methodParameter);
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter methodParameter, 
                                         Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
        try {
            AesCrypto methodAnnotation = methodParameter.getMethodAnnotation(AesCrypto.class);
            AesCrypto classAnnotation = methodParameter.getContainingClass().getAnnotation(AesCrypto.class);
            
            // 优先使用方法级别的注解，其次使用类级别的注解
            AesCrypto annotation = methodAnnotation != null ? methodAnnotation : classAnnotation;
            
            if (annotation != null && BooleanUtil.isTrue(annotation.open())) {
                log.debug("开始解密请求体: {}", methodParameter.getMethod().getName());
                
                // 验证配置
                if (key == null || key.trim().isEmpty()) {
                    log.error("加密密钥未配置");
                    throw new IOException("加密配置错误");
                }
                
                // 创建解密处理器
                return new DecryptHttpInputMessageHandler(inputMessage, charset, key, cryptoService);
            }
            
            return inputMessage;
            
        } catch (Exception e) {
            log.error("请求体解密处理失败", e);
            throw new IOException("请求体解密失败: " + e.getMessage(), e);
        }
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, 
                              Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        log.debug("请求体读取完成: {}", methodParameter.getMethod().getName());
        return body;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, 
                                Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        log.debug("处理空请求体: {}", methodParameter.getMethod().getName());
        return body;
    }

    /**
     * 检查是否有AES加密注解
     */
    private boolean hasAesCryptoAnnotation(MethodParameter methodParameter) {
        // 检查方法级别的注解
        if (methodParameter.getMethod() != null && 
            methodParameter.getMethod().isAnnotationPresent(AesCrypto.class)) {
            return true;
        }
        
        // 检查类级别的注解
        return methodParameter.getContainingClass().isAnnotationPresent(AesCrypto.class);
    }
}
